﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Audio;
using Microsoft.Xna.Framework.Content;
using Microsoft.Xna.Framework.GamerServices;
using Microsoft.Xna.Framework.Graphics;
using Microsoft.Xna.Framework.Input;
using Microsoft.Xna.Framework.Media;
using System.Xml;

namespace GameVLTK
{
    public class Player : MoveableUnit
    {
        #region Thuộc tính nhân vật

        //Các chỉ số liên quan đến người chơi

        //Cập độ level hiện tại 
        private int _Level;

        public int Level
        {
            get { return _Level; }
            set { _Level = value; }
        }

        //Điểm danh vọng
        private int _DiemDanhVong;

        public int DiemDanhVong
        {
            get { return _DiemDanhVong; }
            set { _DiemDanhVong = value; }
        }

        //Điểm kinh nghiệm
        private int _DiemKinhNghiem;

        public int DiemKinhNghiem
        {
            get { return _DiemKinhNghiem; }
            set { _DiemKinhNghiem = value; }
        }

        //Chỉ số nội lực
        private int _Mana;

        public int Mana
        {
            get { return _Mana; }
            set { _Mana = value; }
        }

        //Chỉ số thể lực
        private int _TheLuc;

        public int TheLuc
        {
            get { return _TheLuc; }
            set { _TheLuc = value; }
        }

        //Danh sách các trạng bị của người chơi
        private List<Equipment> _Equipments; 

        public List<Equipment> Equipments
        {
            get { return _Equipments; }
            set { _Equipments = value; }
        }

       
        public override int HP
        {
            get{return base.HP;}
            set
            {
                base.HP = value;
                if (this.HP <= 0)
                {
                    //Player ở trạng thái chết
                    this.PrevState = this.CurrentState;
                    this.CurrentState = this.PrevState;

                    //Cho quay về vị trí xuất phát
                }
            }
        }
        
       

        //Đối thủ của Player
        private Killer _CompetidorUnit;

        public Killer CompetidorUnit
        {
            get { return _CompetidorUnit; }
            set { _CompetidorUnit = value; }
        }

        private bool _WillAttack;

        public bool WillAttack
        {
            get { return _WillAttack; }
            set { 
                _WillAttack = value;
                if (value== false)
                {
                    this.CompetidorUnit.PrevState = this.CompetidorUnit.CurrentState;
                    this.CompetidorUnit.CurrentState = (int)Global.enmStates.DUNG_YEN;
                }
            }
        }

        #endregion

        /// <summary>
        /// Khởi tạo player từ file Xml
        /// </summary>
        /// <param name="content"></param>
        /// <param name="doc"></param>
        public Player(ContentManager content, XmlDocument doc)
                    :base(content,doc)
        {
            this.HP = 100;

            //Khởi tạo trạng thái ban đầu cho nhân vật 
            this.CurrentState = (int)Global.enmStates.DUNG_YEN;
            this.PrevState = (int)Global.enmStates.DUNG_YEN;

            //Khởi tạo hướng ban đầu cho nhân vật
            this.CurrentDirection = (int)Global.enmDirs.DOWN;
            this.PrevDirection = this.CurrentDirection;

            //Đường dẫn đến Image
            string pathImage = Global.PATH_IMAGES;

            
            XmlNode nPlayer = doc.SelectSingleNode("//PLAYER");
            this.Logic = new Vector2(float.Parse(nPlayer.Attributes["X"].Value),
                                       float.Parse(nPlayer.Attributes["Y"].Value));

            //Lấy tên cho đối tượng
            this.Name = nPlayer.Attributes["Name"].Value;

            //Tọa độ thực tế dùng để vẻ đối tượng lên World Map
            this.TopLeft = this.Logic + Global.TopLeft;
             
            //Tên nhân vật
            string prefix = nPlayer.Attributes["Prefix"].Value;

            //Số lượng trạng thái của nhân vật
            this.Sprites = new List<MySprite>();
            this.nSprites = nPlayer.ChildNodes.Count;

            this._FrameOfThatDirs = new int[this.nSprites];

            Texture2D[] txttures = null;
            string path= pathImage + prefix;
            int nTextures= 0;
            XmlNode nState= null;
            string prefixState = null;
            MySprite mySprite = null;
            for (int i = 0; i < this.nSprites; i++)
            {
                nState= nPlayer.ChildNodes[i];
                nTextures= int.Parse(nState.Attributes["So_Luong"].Value);
                prefixState = nState.Attributes["Prefix"].Value;

                txttures = LoadTextures(content, path + prefixState + "/", nTextures, i);

                mySprite = new MySprite(txttures, this.TopLeft);
                mySprite.FrameSequence = CalcFrameSeq();
                this.Sprites.Add(mySprite);
            }

            //Tính kích thước Players, không có chính xác ?????????????????????????????????
            this.Size = new Vector2(this.Sprites.ElementAt((int)Global.enmStates.DUNG_YEN).Textures[0].Width,
                                    this.Sprites.ElementAt((int)Global.enmStates.DUNG_YEN).Textures[0].Height);

            //Qui định thứ tự vẽ trên Map
            this.Z_Index = (float)this.TopLeft.Y;

          

            //Ánh hào quang cho Player
            this.Auras = new List<Aura>();
            this.Auras.Add((Aura)Map.PrototypeAuras.GetPrototypeById(0));
            this.Auras.Add((Aura)Map.PrototypeAuras.GetPrototypeById(1));
            this.CurrentAura = 0;

            //Khởi tạo Skill cho nhân vật
            this.Skills = new List<Skill>();
            this.Skills.Add((Skill)Map.PrototypeSkills.GetPrototypeById(0));
            this.Skills.Add((Skill)Map.PrototypeSkills.GetPrototypeById(1));
            this.Skills.Add((Skill)Map.PrototypeSkills.GetPrototypeById(2));
            this.Skills.Add((Skill)Map.PrototypeSkills.GetPrototypeById(3));
            this.CurrentSkill = 2;
        }

        /// <summary>
        /// 
        /// </summary>
        public override void Update(GameTime gameTime)
        {
            GartherInput(Mouse.GetState(), gameTime);

          
            //Trường hợp nhân vật đang sử dụng Skill
            if (this.IsSkillActive)
            {
                if (Skills[this.CurrentSkill].IsSkillActive)
                {
                    this.Skills[this.CurrentSkill].Update(gameTime);
                }
                else
                {
                    this.IsSkillActive = false;
                }

            }

            if (this.CurrentState == (int)Global.enmStates.DI_BO)
            {
                //Thay đổi View Port của màn hình
                ChangeViewPort();

                //Cho nhân vật di chuyển
                this.MotionModule.OnMotion(this, gameTime); 
            }

           
            /*if (this.WillAttack && this.CurrentState != (int)Global.enmStates.TAN_CONG)
                   CheckCollision();*/
            
          
            if (this.CurrentState == (int)Global.enmStates.TAN_CONG)
            {
                //Nếu nó đánh hết một đòn thì mới trừ máu con Killer xuống
                if (this.CompetidorUnit.HP > 0)
                {
                    //Qui định khoảng thời gian để mất một giọt máu
                    this.TimeOld += gameTime.ElapsedGameTime.Milliseconds;
                    if (this.TimeOld > 100)
                    {
                        this.TimeOld = 0;
                        this.CompetidorUnit.HP -= 1;

                        if (this.IsSkillActive == false) 
                           Global.BroadCastEvents(Global.EVENTS.GM_PLAYER_FIRED_SKILL, this, null, null);
                    }
                }
            }

            //Update vị trí cho thành HealthBar
            this.HealthBar.HealthBarPosition = new Vector2(this.TopLeft.X + this.Size.X/4 ,                     
                                                           this.TopLeft.Y- 5);
            this.HealthBar.HealthDotPosition = new Vector2(this.TopLeft.X + this.Size.X / 4 + 1, 
                                                           this.TopLeft.Y - 4);

            //Update vị trí cho Aura
            this.Auras[this.CurrentAura].TopLeft = new Vector2(this.TopLeft.X- 22, 
                                            this.TopLeft.Y + this.Size.Y/2);

            this.Auras[this.CurrentAura].Update(gameTime);

            //Update vị trí Dot trên Mini Map
            this.Logic = this.TopLeft - Global.TopLeft;
            this.UnitDot.DotLogic = new Vector2(this.Logic.X / Map.MiniMap.Scale,
                                  this.Logic.Y / Map.MiniMap.Scale);
            
         
            //Update nhân vật
            this.Sprites[this.CurrentState].Update(gameTime);
        }

       

        /// <summary>
        /// 
        /// </summary>
        public override void Draw(GameTime gameTime, SpriteBatch spriteBatch)
        {
            //Vẽ Ánh hào quang cho Player
            this.Auras[this.CurrentAura].Draw(gameTime, spriteBatch);

            //Thanh HealBar cho Player
            this.HealthBar.Draw(gameTime, spriteBatch);

            //Vẽ Skill
            if (this.IsSkillActive)
            {
                this.Skills[this.CurrentSkill].Draw(gameTime, spriteBatch);
            }

            //Vẽ nhân vật lên
            this.Sprites[this.CurrentState].Draw(gameTime, spriteBatch);

            //Vẽ tên nhân vật lên
            Global.DrawName(spriteBatch, this.Name,
                             this.TopLeft, this.Size, Color.DeepPink);
            
        }
        /// <summary>
        /// Kiểm tra collsion với Killer
        /// </summary>
       /* private void CheckCollision()
        {
            //Khi Player va chạm với Killer và có lệnh đánh Killer thì nó
            //sẽ đánh Killer
            if (this.CompetidorUnit != null && this.CompetidorUnit.HP> 0)
                if (Global.IsCollisioned(this,(Killer)this.CompetidorUnit) && this.WillAttack)
                {
                    this.PrevState = this.CurrentState;
                    this.CurrentState = (int)Global.enmStates.TAN_CONG;

                    //Bắn event cho Killer biết để nó tấn công lại Player
                    GameEntity[] recievers = new GameEntity[1];
                    recievers[0] = (GameEntity)this.CompetidorUnit;
                    object[] args = new object[1];
                    args[0] = this.TopLeft;
                    Global.BroadCastEvents(Global.EVENTS.GM_PLAYER_ATTACK_KILLER,
                                           this, args, recievers);
                }
        }*/
        /// <summary>
        /// Thay đổi View Port của màn hình
        /// </summary>
        private void ChangeViewPort()
        {
            Vector2 ufo = Global.TopLeft;

            //Xét xem vị trí topleft của Map có bị thay đổi hay không?
            bool isChanged = false;

            //Nếu vị trí con chuột di chuyển quan biên bên trái thì 
            //Map phải kéo qua bên phải
            int DISTANCE = 300;
            int l = 3;
            if (this.TopLeft.X - DISTANCE < 0)
            {
                if (ufo.X < 0)
                {
                    ufo.X += l;
                    isChanged = true;
                }
            }
            else
                //Nếu vị trí con chuột di chuyển quan biên bên phải thì 
                //Map phải kéo qua bên trái
                if (this.TopLeft.X + DISTANCE > Global.SCREEN_WIDTH)
                {
                    if (ufo.X > -(Global.MAP_WIDTH - Global.SCREEN_WIDTH))
                    {
                        ufo.X -= l;
                        isChanged = true;
                    }
                }
            //Nếu vị trí con chuột di chuyển lên phía trên thì 
            //Map phải kéo xuống dưới
            if (this.TopLeft.Y + DISTANCE > Global.SCREEN_HEIGHT)
            {
                if (ufo.Y > -(Global.MAP_HEIGHT - Global.SCREEN_HEIGHT))
                {
                    ufo.Y -= l;
                    isChanged = true;
                }
            }
            else
                //Nếu vị trí con chuột di chuyển xuống phía dưới thì 
                //Map phải kéo lên phía trên
                if (this.TopLeft.Y - DISTANCE < 0)
                {
                    if (ufo.Y < 0)
                    {
                        ufo.Y += l;
                        isChanged = true;
                    }
                }

            if (isChanged == true)
            {
                //Vị trí tọa độ bị dịch chuyển
                Vector2 topLeftChanged = ufo - Global.TopLeft;
                Object[] args = new object[1];
                args[0] = topLeftChanged;

                Global.TopLeft = ufo;
                Global.BroadCastEvents(Global.EVENTS.GM_MAP_TOPLEFT_CHANGED, this,
                                        args, null);
            }
        }
      
        private void GartherInput(MouseState mouseState, GameTime gameTime)
        {
         
            if (mouseState.LeftButton == ButtonState.Pressed)
            {
                //Kiểm tra xem Player có click vào Killer nào đó hay không?
                //Nếu Player đang đánh mà nó click bên ngoài đối tượng Killer thì dừng đánh
                if (this.CurrentState == (int)Global.enmStates.TAN_CONG)
                {
                    if (this.CompetidorUnit.IsClicked(mouseState)== false)
                    {
                        this.WillAttack = false;
                    }
                }

                //Lấy tọa độ click lên màn hình= tọa độ thực
                Vector2 screenPoint = new Vector2(mouseState.X, mouseState.Y);

                //Xác định vị trí Cell target= tọa độ logic so với đối tượng Map
                Vector2 targetCell = Map.Point2Cell(screenPoint);

                if (targetCell.X >= 0 && targetCell.X < Map.nRows &&
                       targetCell.Y >= 0 && targetCell.Y < Map.nCols)
                {
                    // Lấy ô mà nhân vật đang đứng
                    Vector2 currCell = Map.Point2Cell(new Vector2(this.TopLeft.X + this.Size.X / 2,
                                                               this.TopLeft.Y + this.Size.Y / 2));


                    //Xét xem vị trí đích có trùng với vị trí mà Player đang đứng hay không?
                    Vector2 tmp = new Vector2((int)Math.Round(currCell.X), (int)Math.Round(currCell.Y));
                    if ((int)Math.Round(currCell.X) != (int)Math.Round(targetCell.X) ||
                              (int)Math.Round(currCell.Y) != (int)Math.Round(targetCell.Y))
                    {
                       
                        this.IsMoving = true;

                        //Cập nhật lại trạng thái đang đi bộ cho đối tượng
                        this.PrevState = this.CurrentState;

                        //Cập nhật trạng thái hiện tại cho nhân vật
                        this.CurrentState = (int)Global.enmStates.DI_BO;

                      
                        //Mỗi lần di chuyển cho nhân vật di chuyển 2 Cell liên tiếp nhau
                        GoToLogicalXY(screenPoint);

                    }
                }
            }
        }

        /// <summary>
        /// Sử lý event phát sinh trong game liên quan đến đối tượng Player
        /// </summary>
        public override int OnEvent(Global.EVENTS eventID, object sender, object[] args)
        {
            int kq = 0;
            switch (eventID)
            {
                case Global.EVENTS.GM_KILLER_DIED:
                    {
                        this.PrevState = this.CurrentState;
                        this.CurrentState = (int)Global.enmStates.DUNG_YEN;

                        this.IsMoving = false;
                        this.WillAttack = false;

                        kq = 1;
                        break;
                    }
                case Global.EVENTS.GM_KILLER_CLICKED:
                    {
                        //this.WillAttack = true;
                        this.CompetidorUnit = (Killer)sender;

                        //Cập nhật lại trạng thái cho Player
                        this.PrevState = this.CurrentState;
                        this.CurrentState = (int)Global.enmStates.TAN_CONG;

                        GameEntity[] recievers = new GameEntity[1];
                        recievers[0] = (GameEntity)this.CompetidorUnit;
                        object[] tmps= new object[1];
                        tmps[0] = this.TopLeft;
                        Global.BroadCastEvents(Global.EVENTS.GM_PLAYER_ATTACK_KILLER,
                                               this, tmps, recievers);
                        kq = 1;
                        break;
                    }
                case Global.EVENTS.GM_MAP_TOPLEFT_CHANGED:
                    {
                        this.TopLeft += (Vector2)args[0];
                        break;
                    }
                case Global.EVENTS.GM_PLAYER_FIRED_SKILL:
                    {
                        //Kiểm tra nó có phải là thằng bắn event bắn skill lên không?
                        if (this == sender)
                        {
                             //Tính toán vị trí cho Skill
                            /*this.Skills[this.CurrentSkill].PrevDirection = this.Skills[this.CurrentSkill].CurrentDirection;
                            this.Skills[this.CurrentSkill].CurrentDirection = this.CurrentDirection;*/

                            //Khởi tạo vị trí ban đầu cho Skill
                            //this.Skills[this.CurrentSkill].TopLeft = this.TopLeft + new Vector2(0, this.Size.Y);
                            this.IsSkillActive = true;
                           
                            this.Skills[this.CurrentSkill].TopLeft = new Vector2(this.CompetidorUnit.TopLeft.X - this.Size.X/2,
                                                                      this.CompetidorUnit.TopLeft.Y - this.Size.Y / 2);

                            //Kích hoạt skill
                            this.Skills[this.CurrentSkill].IsSkillActive = true;

                            Global.soundManager.playSound("Fired-Skill");

                            kq = 1;
                        }
                        break;
                    }
                default:
                    break;
            }

            return kq;
        }
    
    }
}
